package com.yt.fras.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yt.fras.constant.ResultCode;
import com.yt.fras.listener.ExcelListener;
import com.yt.fras.pojo.base.JsonResult;
import com.yt.fras.pojo.base.UserInputExcel;
import com.yt.fras.pojo.base.UserOutputExcel;
import com.yt.fras.pojo.entity.*;
import com.yt.fras.pojo.model.Location;
import com.yt.fras.pojo.model.UserInfo;
import com.yt.fras.service.*;
import com.yt.fras.utils.LocationUtil;
import com.yt.fras.utils.RedisUtil;
import com.yt.fras.utils.ResultTool;
import com.yt.fras.utils.SetContent;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static com.yt.fras.constant.AttendanceStatus.ABSENTEEISM;
import static com.yt.fras.constant.RoleConstant.USER;

/**
 * ClassName:BasicController
 * Package:com.yt.fras.controller
 * Description:
 * 基础模块
 *
 * @date:2021/10/27 22:10
 * @author:yt
 */
@RestController
@Api(tags = "基础模块")
@RequestMapping("/fras")
public class BasicController {

    @Autowired
    private UserService userService;

    @Autowired
    private MailService mailService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private FaceServer faceServer;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 注册
     *
     * @param username
     * @param password
     * @param email
     * @param phone
     * @param image
     * @return
     */
    @PostMapping("/register/{username}/{password}/{email}/{phone}")
    @ApiOperation(value = "注册用户")
    @ApiResponses({
            @ApiResponse(code = 200, message = "注册成功！"),
            @ApiResponse(code = 200, message = "注册成功！图片上传失败！请进入用户页面重新上传！"),
            @ApiResponse(code = 0, message = "注册失败！"),
            @ApiResponse(code = 500, message = "系统出现错误~")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "username", value = "用户名", required = true),
            @ApiImplicitParam(paramType = "path", name = "password", value = "密码", required = true),
            @ApiImplicitParam(paramType = "path", name = "email", value = "邮箱", required = true),
            @ApiImplicitParam(paramType = "path", name = "phone", value = "手机号", required = true),
            @ApiImplicitParam(paramType = "body", name = "image", value = "图片base64编码", required = true)
    })
    public String register(@PathVariable String username, @PathVariable String password, @PathVariable String email, @PathVariable String phone, @RequestParam String image) {
        User user = new User();
        user.setUsername(username);
        user.setPassword(passwordEncoder.encode(password));
        user.setEmail(email);
        user.setPhone(phone);
        JsonResult result;
        if (userService.save(user)) {
            userRoleService.save(new UserRole(user.getId(), USER));
            if (StringUtils.isNotBlank(image)) {
                String[] split = image.split(",");
                if (split.length > 1) {
                    image = split[1];
                }
                if (faceServer.faceRegister(user.getId(), image)) {
                    result = ResultTool.success();
                    result.setMsg("注册成功！");
                } else {
                    result = ResultTool.success();
                    result.setMsg("注册成功！图片上传失败！请进入用户页面重新上传！");
                }
            } else {
                result = ResultTool.success();
                result.setMsg("注册成功！图片上传失败！请进入用户页面重新上传！");
            }
            mailService.sendHtmlMail(user.getEmail(), "注册成功！", SetContent.register(username));
        } else {
            result = ResultTool.fail();
            result.setMsg("注册失败！");

        }
        return JSON.toJSONString(result);
    }

    /**
     * 忘记密码
     *
     * @param username
     * @param password
     * @param emailCode
     * @return
     */
    @PutMapping("/resetPassword/{username}/{password}/{emailCode}")
    @ApiOperation(value = "忘记密码")
    @ApiResponses({
            @ApiResponse(code = 200, message = "重置成功！"),
            @ApiResponse(code = 0, message = "重置失败！"),
            @ApiResponse(code = 500, message = "系统出现错误~")
    })
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "username", value = "用户名", required = true),
            @ApiImplicitParam(paramType = "path", name = "password", value = "密码", required = true),
            @ApiImplicitParam(paramType = "path", name = "emailCode", value = "邮箱验证码", required = true),

    })
    public String resetPassword(@PathVariable String username, @PathVariable String password, @PathVariable int emailCode) {

        int emailCode1 = (int) redisUtil.hGet(username, "emailCode");
        JsonResult result;
        if (emailCode1 == emailCode) {
            if (userService.resetPassword(username, passwordEncoder.encode(password))) {
                result = ResultTool.success();
                result.setMsg("重置成功！");

            } else {
                result = ResultTool.fail();
                result.setMsg("重置失败！");

            }
        } else {
            result = ResultTool.fail();
            result.setMsg("验证码错误！");

        }
        return JSON.toJSONString(result);
    }

    /**
     * 会话过期
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("/session/invalid")
    @ResponseStatus(code = HttpStatus.UNAUTHORIZED)
    @ApiOperation(value = "会话过期")
    @ApiResponses({
            @ApiResponse(code = 2010, message = "会话过期"),

    })
    public void sessionInvalid(HttpServletResponse response) throws IOException {
        JsonResult result = ResultTool.fail(ResultCode.USER_SESSION_EXPIRED);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(JSON.toJSONString(result));
    }

    /*
     * 以下为测试接口
     */


    @GetMapping("/getIpLocation/{ip}")
    public String getIpLocation(@PathVariable String ip) {
        LocationUtil locationUtil = new LocationUtil();
        Location ipLocation = locationUtil.getIpLocation(ip);
        JsonResult result = ResultTool.success(ipLocation);
        return JSON.toJSONString(result);
    }


    @Autowired
    private ManagementGroupService managementGroupService;

    @Autowired
    private GroupUserService groupUserService;

    @Autowired
    private AttendanceService attendanceService;

    @Autowired
    private AttendanceUserService attendanceUserService;

    @Autowired
    private ThreadPoolTaskExecutor applicationTaskExecutor;

    @Autowired
    private LocationUtil locationUtil;

    @GetMapping("/test")
    public String test() {
        List<Attendance> attendances = attendanceService.list();
        attendances.forEach(attendance -> {
            //ManagementGroup managementGroup = managementGroupService.getById(attendance.getGroupId());
            //attendance.setTotalCount(managementGroup.getCount());
            //attendanceService.updateById(attendance);
            Location ipLocation = locationUtil.getIpLocation("58.23.36.253");
            String[] location = ipLocation.getLocation().split(",");
            redisUtil.hSet(attendance.getId(), "longitude", location[0]);
            redisUtil.hSet(attendance.getId(), "latitude", location[1]);
        });

        JsonResult result = ResultTool.success();
        return JSON.toJSONString(result);
    }

    @GetMapping("/test1")
    public String test1() {
        List<ManagementGroup> managementGroups = managementGroupService.list();
        List<User> users = userService.list();
        managementGroups.forEach(managementGroup -> {
                    List<GroupUser> groupUsers = new ArrayList<>();
                    final int[] count = {0};
                    managementGroup.setCount(0);
                    CompletableFuture<Void> groupUsersFuture = CompletableFuture.runAsync(() -> {
                        for (User user : users) {
                            if (!managementGroup.getAdminId().equals(user.getId())) {
                                QueryWrapper<GroupUser> wrapper = new QueryWrapper<>();
                                wrapper.eq("user_id", user.getId())
                                        .eq("group_id", managementGroup.getId());
                                if (groupUserService.getOne(wrapper) == null) {
                                    GroupUser groupUser = new GroupUser();
                                    groupUser.setGroupId(managementGroup.getId());
                                    groupUser.setUserId(user.getId());
                                    count[0]++;
                                    groupUsers.add(groupUser);
                                }
                            }
                        }
                    }, applicationTaskExecutor);
                    try {
                        CompletableFuture.allOf(groupUsersFuture).get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                    groupUserService.saveBatch(groupUsers);
                    managementGroup.setCount(managementGroup.getCount() + count[0]);
                    managementGroupService.updateById(managementGroup);
                }
        );
        JsonResult result = ResultTool.success();
        return JSON.toJSONString(result);
    }

    @GetMapping("/test2")
    public String test2() {
        List<Attendance> attendances = attendanceService.list();
        attendances.forEach(attendance -> {
            List<UserInfo> userInfoList = userService.getUserInfoListByGroup(attendance.getGroupId());
            List<AttendanceUser> attendanceUserList = new ArrayList<>();
            CompletableFuture<Void> attendanceUsersFuture = CompletableFuture.runAsync(() -> {
                userInfoList.forEach(userInfo -> {
                    QueryWrapper<AttendanceUser> wrapper = new QueryWrapper<>();
                    wrapper.eq("user_id", userInfo.getId())
                            .eq("attendance_id", attendance.getId());
                    if (attendanceUserService.getOne(wrapper) == null) {
                        AttendanceUser attendanceUser = new AttendanceUser();
                        attendanceUser.setAttendanceId(attendance.getId());
                        attendanceUser.setUserId(userInfo.getId());
                        attendanceUser.setStatus(ABSENTEEISM);
                        attendanceUser.setAttendanceTime(new Date());
                        attendanceUserList.add(attendanceUser);
                    }
                });
            }, applicationTaskExecutor);
            try {
                CompletableFuture.allOf(attendanceUsersFuture).get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            attendanceUserService.saveBatch(attendanceUserList);
        });
        JsonResult result = ResultTool.success();
        return JSON.toJSONString(result);
    }

    @GetMapping("/test3")
    public String test3() throws ExecutionException, InterruptedException {
        List<ManagementGroup> managementGroups = managementGroupService.list();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        System.out.println("当前系统时间: " + simpleDateFormat.format(calendar.getTime()));
        JsonResult result = ResultTool.success();
        for (ManagementGroup managementGroup : managementGroups) {
            for (int i = 0; i < 3; i++) {
                Date current = new Date();
                calendar.add(Calendar.HOUR, i - 1);
                Date start = calendar.getTime();
                calendar.add(Calendar.DATE, 1);
                Date end = calendar.getTime();
                String description = "测试10" + i;
                Attendance attendance = new Attendance();
                attendance.setDescription(description);
                attendance.setGroupId(managementGroup.getId());
                if (current.getTime() < start.getTime()) {
                    attendance.setStatus(1);
                } else if (current.getTime() > end.getTime()) {
                    attendance.setStatus(0);
                } else {
                    attendance.setStatus(2);
                }
                attendance.setActualCount(0);
                attendance.setTotalCount(managementGroup.getCount());
                attendance.setStartTime(start);
                attendance.setEndTime(end);
                if (attendanceService.save(attendance)) {
                    List<UserInfo> userInfoList = userService.getUserInfoListByGroup(managementGroup.getId());
                    List<AttendanceUser> attendanceUserList = new ArrayList<>();
                    CompletableFuture<Void> attendanceUsersFuture = CompletableFuture.runAsync(() -> {
                        userInfoList.forEach(userInfo -> {
                            AttendanceUser attendanceUser = new AttendanceUser();
                            attendanceUser.setAttendanceId(attendance.getId());
                            attendanceUser.setUserId(userInfo.getId());
                            attendanceUser.setStatus(ABSENTEEISM);
                            attendanceUser.setAttendanceTime(new Date());
                            attendanceUserList.add(attendanceUser);
                        });
                    }, applicationTaskExecutor);

                    CompletableFuture.allOf(attendanceUsersFuture).get();
                    attendanceUserService.saveBatch(attendanceUserList);
                    Location ipLocation = locationUtil.getIpLocation("218.104.130.52");
                    String[] location = ipLocation.getLocation().split(",");
                    redisUtil.hSet(attendance.getId(), "longitude", location[0]);
                    redisUtil.hSet(attendance.getId(), "latitude", location[1]);
                }
                calendar = Calendar.getInstance();
            }
        }
        return JSON.toJSONString(result);
    }

    @Autowired
    private ExcelService excelService;

    @PostMapping("/test4/{groupId}")
    public String test4(@RequestParam("file") MultipartFile file, @PathVariable String groupId) throws IOException {

        EasyExcel.read(file.getInputStream(), UserInputExcel.class, new ExcelListener(excelService, groupId)).sheet().doRead();

        JsonResult result = ResultTool.success();
        return JSON.toJSONString(result);
    }

    @GetMapping("/test5/{attendanceId}")
    public String test5(HttpServletResponse response, @PathVariable String attendanceId) throws IOException {
        List<UserOutputExcel> userOutputExcels = attendanceUserService.getAbsentUsers(attendanceId);
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), UserOutputExcel.class).sheet("模板").doWrite(userOutputExcels);
        JsonResult result = ResultTool.success();
        return JSON.toJSONString(result);
    }
}
